package com.torry.replay.api.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.torry.replay.api.request.GetDragonInfoRequest;
import com.torry.replay.api.request.GetSeatsRequest;
import com.torry.replay.api.request.SaveDragonInfoRequest;
import com.torry.replay.api.result.GetDragonInfoResult;
import com.torry.replay.application.exception.ReplayExceptionEnum;
import com.torry.replay.infras.entity.DragonDO;
import com.torry.replay.infras.entity.DragonDetailDO;
import com.torry.replay.infras.entity.SeatDO;
import com.torry.replay.infras.repo.DragonDetailRepository;
import com.torry.replay.infras.repo.DragonRepository;
import com.torry.replay.infras.repo.SeatRepository;
import com.torry.replay.integration.StockApi;
import com.torry.replay.integration.result.SyncDragonResult;
import com.zen.boot.common.util.Preconditions;
import com.zen.boot.starter.mybatisplus.base.Entity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author torry.wang
 */
@RestController
@RequestMapping("/dragon")
@Api(tags = "席位 | 龙虎榜")
public class DragonController {

    @Resource
    private SeatRepository seatRepository;

    @Resource
    private DragonRepository dragonRepository;
    @Resource
    private DragonDetailRepository dragonDetailRepository;

    @Resource
    private StockApi stockApi;

    @PostMapping("saveSeatInfo")
    @ApiOperation(value = "保存席位信息")
    public Boolean saveSeatInfo(@RequestBody SeatDO seatDO) {
        int count = seatRepository.count(new LambdaQueryWrapper<SeatDO>().eq(SeatDO::getSeatName, seatDO.getSeatName()).ne(seatDO.getId() != null, SeatDO::getSeatName, seatDO.getSeatName()));
        Preconditions.ofTrue(count == 0, ReplayExceptionEnum.SEAT_ALREADY_EXIST);
        return seatRepository.saveOrUpdate(seatDO);
    }

    @GetMapping("getSeats")
    @ApiOperation(value = "获取席位列表")
    public List<SeatDO> getSeats(@ModelAttribute GetSeatsRequest request) {
        LambdaQueryWrapper<SeatDO> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(request.getName())) {
            wrapper.like(StringUtils.isNotBlank(request.getName()), SeatDO::getSeatName, request.getName()).or().like(StringUtils.isNotBlank(request.getName()), SeatDO::getNickName, request.getName());
        }
        List<SeatDO> seats = seatRepository.list(wrapper);
        seats.forEach(e -> {
            if (StringUtils.isNotBlank(e.getNickName())) {
                e.setSeatName(e.getNickName());
            }
        });
        return seats;
    }

    @GetMapping("getSeatInfo/{id}")
    @ApiOperation(value = "获取席位列表")
    public SeatDO getSeatInfo(@PathVariable Long id) {
        return seatRepository.getById(id);
    }

    @PostMapping("saveDragonInfo")
    @ApiOperation(value = "保存龙虎榜信息")
    public Boolean saveDragonInfo(@RequestBody SaveDragonInfoRequest request) {
        int count = dragonRepository.count(new LambdaQueryWrapper<DragonDO>()
                .eq(DragonDO::getDate, request.getDate())
                .eq(DragonDO::getName, request.getName())
                .ne(request.getId() != null, DragonDO::getId, request.getId()));
        Preconditions.ofTrue(count == 0, ReplayExceptionEnum.CURRENT_DATE_DRAGON_ALREADY_EXIST);

        DragonDO dragonDO = new DragonDO();
        dragonDO.setDate(request.getDate());
        dragonDO.setName(request.getName());
        dragonDO.setRangePercent(request.getRangePercent());
        dragonRepository.saveOrUpdate(dragonDO);

        if (request.getId() != null) {
            dragonDetailRepository.remove(new LambdaUpdateWrapper<DragonDetailDO>().eq(DragonDetailDO::getDragonId, request.getId()));
        }
        List<DragonDetailDO> details = request.getDetails().stream().map(e -> {
            DragonDetailDO dragonDetailDO = new DragonDetailDO();
            dragonDetailDO.setDragonId(dragonDO.getId());
            dragonDetailDO.setSeatId(e.getSeatId());
            dragonDetailDO.setBuyAmount(e.getBuyAmount());
            dragonDetailDO.setSellAmount(e.getSellAmount());
            return dragonDetailDO;
        }).collect(Collectors.toList());
        return dragonDetailRepository.saveBatch(details);
    }

    @GetMapping("getDragonInfoByDate")
    @ApiOperation(value = "获取指定日期龙虎榜")
    private List<GetDragonInfoResult> getDragonInfo(@ModelAttribute @Valid GetDragonInfoRequest request) {
        LambdaQueryWrapper<DragonDO> wrapper = new LambdaQueryWrapper<DragonDO>().eq(DragonDO::getDate, request.getDate()).eq(StringUtils.isNotBlank(request.getName()), DragonDO::getName, request.getName());

        if (request.getSeatId() != null) {
            List<DragonDO> list = dragonRepository.list(wrapper);
            if (CollectionUtils.isNotEmpty(list)) {
                HashSet<Long> dragonIds = list.stream().map(Entity::getId).collect(Collectors.toCollection(HashSet::new));
                List<Long> realDragonIds = dragonDetailRepository.listObjs(new LambdaQueryWrapper<DragonDetailDO>()
                        .eq(DragonDetailDO::getSeatId, request.getSeatId())
                        .in(DragonDetailDO::getDragonId, dragonIds)
                        .select(DragonDetailDO::getDragonId), e -> Long.parseLong(String.valueOf(e)));
                wrapper.in(DragonDO::getId, realDragonIds);
            } else {
                return Collections.emptyList();
            }
        }
        List<DragonDO> dragons = dragonRepository.list(wrapper);
        if (CollectionUtils.isEmpty(dragons)) {
            return Collections.emptyList();
        }
        return dragons.stream().map(dragon -> dragonDetailRepository.getDragonDetailsByDragonId(dragon.getId())).collect(Collectors.toList());
    }

    @GetMapping("getDragonDetailsInfo/{dragonId}")
    @ApiOperation(value = "获取龙虎榜详情")
    private GetDragonInfoResult getDragonDetailsInfo(@PathVariable Long dragonId) {
        DragonDO dragon = dragonRepository.getById(dragonId);
        if(dragon == null) return null;
        return dragonDetailRepository.getDragonDetailsByDragonId(dragon.getId());
    }

    @GetMapping("getRecentMonthDragonInfo/{name}")
    @ApiOperation(value = "获取最近一个月龙虎榜")
    private List<GetDragonInfoResult> getRecentMonthDragonInfo(@PathVariable(value = "name") String name) {
        LocalDate now = LocalDate.now();
        LocalDate startDate = now.minusMonths(1);

        List<DragonDO> dragons = dragonRepository.list(new LambdaQueryWrapper<DragonDO>().ge(DragonDO::getDate, startDate).le(DragonDO::getDate, now).eq(DragonDO::getName, name));
        if (CollectionUtils.isEmpty(dragons)) return Collections.emptyList();
        return dragons.stream().map(dragon -> dragonDetailRepository.getDragonDetailsByDragonId(dragon.getId())).collect(Collectors.toList());
    }

    @GetMapping("syncDragonInfos/{date}")
    @ApiOperation(value = "同步龙虎榜信息")
    public List<SyncDragonResult> syncDragonInfos(@PathVariable String date) {
        return stockApi.getTodayDragonList(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
    }
}